struct Vec2i
{
    struct Comparison
    {
        bool operator()(const Vec2i &a, const Vec2i &b) const
        {
            if(a.x == b.x) return (a.y < b.y);
            return (a.x < b.x);
        }
        static bool Compare(const Vec2i &a, const Vec2i &b)
        {
            if(a.x == b.x) return (a.y < b.y);
            return (a.x < b.x);
        }
    };

    //
    // Initalization
    //
    inline Vec2i();
    inline Vec2i(const Vec2i &V);
    inline Vec2i(int _x, int _y);
    inline Vec2i(unsigned int _x, unsigned int _y);
    inline Vec2i(int _x, unsigned int _y);
    inline Vec2i(unsigned int _x, int _y);

    //
    // Assignment
    //
    inline Vec2i& operator = (const Vec2i &V);

    //
    // Overloaded operators
    //
    inline Vec2i& operator *= (int right);
    inline Vec2i& operator /= (int right);
    inline Vec2i& operator += (const Vec2i &right);
    inline Vec2i& operator -= (const Vec2i &right);

    //
    // Accessors
    //
    inline float Length() const;
    inline float LengthSq() const;
    inline int MaxElement() const;

    //
    // Local data
    //
    int x, y;

    //
    // Constants
    //
    static const Vec2i Origin;
    static const Vec2i eX;
    static const Vec2i eY;

    //
    // Static functions
    //
    inline static Vec2i Maximize(const Vec2i &left, const Vec2i &right);
    inline static Vec2i Minimize(const Vec2i &left, const Vec2i &right);
    inline static float Dist(const Vec2i &left, const Vec2i &right);
    inline static float DistSq(const Vec2i &left, const Vec2i &right);
    inline static int DistL1(const Vec2i &left, const Vec2i &right);
};


Vec2i::Vec2i()
{

}

Vec2i::Vec2i(int _x, int _y)
{
    x = _x;
    y = _y;
}

Vec2i::Vec2i(unsigned int _x, unsigned int _y)
{
    x = int(_x);
    y = int(_y);
}

Vec2i::Vec2i(int _x, unsigned int _y)
{
    x = _x;
    y = int(_y);
}

Vec2i::Vec2i(unsigned int _x, int _y)
{
    x = int(_x);
    y = _y;
}

Vec2i::Vec2i(const Vec2i &V)
{
    x = V.x;
    y = V.y;
}

inline Vec2i& Vec2i::operator = (const Vec2i &V)
{
    x = V.x;
    y = V.y;
    return *this;
}

inline Vec2i& Vec2i::operator *= (int right)
{
    x *= right;
    y *= right;
    return *this;
}

inline Vec2i& Vec2i::operator /= (int right)
{
    x /= right;
    y /= right;
    return *this;
}

inline Vec2i& Vec2i::operator += (const Vec2i &right)
{
    x += right.x;
    y += right.y;
    return *this;
}

inline Vec2i& Vec2i::operator -= (const Vec2i &right)
{
    x -= right.x;
    y -= right.y;
    return *this;
}

inline float Vec2i::Length() const
{
    return sqrtf(float(x) * float(x) + float(y) * float(y));
}

inline float Vec2i::LengthSq() const
{
    return float(float(x) * float(x) + float(y) * float(y));
}

inline int Vec2i::MaxElement() const
{
    return Math::Max(x, y);
}

inline Vec2i Vec2i::Maximize(const Vec2i &left, const Vec2i &right)
{
    Vec2i result = right;
    if(left.x > right.x) result.x = left.x;
    if(left.y > right.y) result.y = left.y;
    return result;
}

inline Vec2i Vec2i::Minimize(const Vec2i &left, const Vec2i &right)
{
    Vec2i result = right;
    if(left.x < right.x) result.x = left.x;
    if(left.y < right.y) result.y = left.y;
    return result;
}

inline float Vec2i::Dist(const Vec2i &left, const Vec2i &right)
{
    float XDiff = float(right.x - left.x);
    float YDiff = float(right.y - left.y);
    return sqrtf(XDiff * XDiff + YDiff * YDiff);
}

inline int Vec2i::DistL1(const Vec2i &left, const Vec2i &right)
{
    int XDiff = Math::AbsInt(right.x - left.x);
    int YDiff = Math::AbsInt(right.y - left.y);
    return XDiff + YDiff;
}

inline float Vec2i::DistSq(const Vec2i &left, const Vec2i &right)
{
    float XDiff = float(right.x - left.x);
    float YDiff = float(right.y - left.y);
    return (XDiff * XDiff + YDiff * YDiff);
}

inline Vec2i operator * (const Vec2i &left, int right)
{
    Vec2i Return;
    Return.x = left.x * right;
    Return.y = left.y * right;
    return Return;
}

inline Vec2i operator * (int right, const Vec2i &left)
{
    Vec2i Return;
    Return.x = left.x * right;
    Return.y = left.y * right;
    return Return;
}

inline Vec2i operator / (const Vec2i &left, int right)
{
    Vec2i Return;
    Return.x = left.x / right;
    Return.y = left.y / right;
    return Return;
}

inline Vec2i operator + (const Vec2i &left, const Vec2i &right)
{
    Vec2i Return;
    Return.x = left.x + right.x;
    Return.y = left.y + right.y;
    return Return;
}

inline Vec2i operator - (const Vec2i &left, const Vec2i &right)
{
    Vec2i Return;
    Return.x = left.x - right.x;
    Return.y = left.y - right.y;
    return Return;
}

inline bool operator == (const Vec2i &left, const Vec2i &right)
{
    return (left.x == right.x && left.y == right.y);
}

inline bool operator != (const Vec2i &left, const Vec2i &right)
{
    return (left.x != right.x || left.y != right.y);
}
